package com.bestcem.xm.label.controller.v3;

import cn.hutool.json.JSONUtil;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.domain.web.XmResultJson;
import com.bestcem.xm.common.core.uitls.GRpcUtil;
import com.bestcem.xm.component.security.context.SecurityContextHolder;
import com.bestcem.xm.label.controller.v3.param.CreateLabelRequest;
import com.bestcem.xm.label.controller.v3.param.CreateLabelValueRequest;
import com.bestcem.xm.label.controller.v3.param.UpdateLabelRequest;
import com.bestcem.xm.label.controller.v3.param.UpdateLabelValueRequest;
import com.bestcem.xm.label.controller.v3.vo.label.BaseTimeVo;
import com.bestcem.xm.label.controller.v3.vo.label.LabelVO;
import com.bestcem.xm.label.controller.v3.vo.labelvalue.LabelValueVO;
import com.bestcem.xm.label.enums.MemberTypeEnum;
import com.bestcem.xm.label.grpc.service.param.label.*;
import com.bestcem.xm.label.service.LabelService;
import com.bestcem.xm.label.service.dto.label.LabelDTO;
import com.bestcem.xm.label.service.dto.label.LabelValueDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author dc.wang <dc.wang@idiaoyan.com>
 * @version V1.0
 * @description 标签web处理器
 * @date 2021/8/18
 */
@Slf4j
@RestController
@RequestMapping("/member/ind/v3/label")
public class IndividualLabelController {
    private final LabelService labelService;

    @Autowired
    public IndividualLabelController(LabelService labelService) {
        this.labelService = labelService;
    }

    /**
     * 查询标签、标签值
     *
     * @param id 标签id
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/8/19
     */
    @GetMapping("/{id}")
    public XmResultJson<LabelVO> getLabel(@PathVariable String id, HttpServletRequest request) {
        
        String orgId = SecurityContextHolder.getOrgId();
        DeleteLabelParam param = new DeleteLabelParam();
        param.setOrgId(orgId);
        param.setId(id);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            return XmResultJson.fail(-1, violation.getMessage());
        }

        // 复用批量查询接口
        ServiceResult<List<LabelDTO>> result = labelService.getLabelInfo(Collections.singletonList(id));
        if (!result.isSuccess()) {
            log.error("查询标签异常({})：{}", param, result.getMsg());
            return XmResultJson.fail(-1, result.getMsg());
        }

        List<LabelDTO> labelDTOS = result.getData();
        if (CollectionUtils.isEmpty(labelDTOS)) {
            return XmResultJson.success();
        }
        LabelVO labelVO = this.convert(labelDTOS.get(0));

        return XmResultJson.success(labelVO);
    }

    /**
     * 创建标签、标签值
     *
     * @param request 请求参数
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/8/19
     */
    @PostMapping()
    public XmResultJson<Map<String, String>> insertLabel(@RequestBody CreateLabelRequest request,
                                                             HttpServletRequest httpServletRequest) {
        
        String orgId = SecurityContextHolder.getOrgId();
        CreateLabelParam param = this.convert(request);
        param.setOrgId(orgId);
        // 当前只有个人联系人拥有标签，而且为兼容前端未传此参数，固定为个人联系人
        param.setAttribute(MemberTypeEnum.MEMBER_MTYPE_INDIVIDUAL.getIndex());

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            return XmResultJson.fail(-1, violation.getMessage());
        }

        ServiceResult<String> result = labelService.createLabel(param);
        if (!result.isSuccess()) {
            log.error("创建标签异常({})：{}", param, result.getMsg());
            return XmResultJson.fail(-1, result.getMsg());
        }

        // 为兼容前端返回map组装参数
        Map<String, String> data = new HashMap<>(1);
        data.put("label_id", result.getData());
        return XmResultJson.success(data);
    }

    /**
     * 更新标签、标签值
     *
     * @param id      标签id 目前未使用，暂时保留
     * @param request 请求参数
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/8/19
     */
    @PutMapping("/{id}")
    public XmResultJson<Map<String, String>> updateLabel(@PathVariable String id,
                                                             @RequestBody UpdateLabelRequest request,
                                                             HttpServletRequest httpServletRequest) {
        
        String orgId = SecurityContextHolder.getOrgId();
        UpdateLabelParam param = this.convert(request);
        param.setOrgId(orgId);
        // 当前只有个人联系人拥有标签，而且为兼容前端未传此参数，固定为个人联系人
        param.setAttribute(MemberTypeEnum.MEMBER_MTYPE_INDIVIDUAL.getIndex());

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            return XmResultJson.fail(-1, violation.getMessage());
        }

        ServiceResult<String> result = labelService.updateLabel(param);
        if (!result.isSuccess()) {
            log.error("更新标签异常({})：{}", param, result.getMsg());
            return XmResultJson.fail(-1, result.getMsg());
        }

        // 为兼容前端返回map组装参数
        Map<String, String> data = new HashMap<>(1);
        data.put("label_id", result.getData());
        return XmResultJson.success(data);
    }

    /**
     * 删除标签
     *
     * @param httpServletRequest 请求参数
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/8/19
     */
    @DeleteMapping("/{id}")
    public XmResultJson deleteLabel(@PathVariable String id, HttpServletRequest httpServletRequest) {
        
        String orgId = SecurityContextHolder.getOrgId();

        DeleteLabelParam param = new DeleteLabelParam();
        param.setOrgId(orgId);
        param.setId(id);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            return XmResultJson.fail(-1, violation.getMessage());
        }

        ServiceResult<String> result = labelService.deleteLabel(param);
        if (!result.isSuccess()) {
            log.error("删除标签异常({})：{}", param, result.getMsg());
            return XmResultJson.fail(-1, result.getMsg());
        }

        // 为兼容前端返回map组装参数
        Map<String, String> data = new HashMap<>(1);
        data.put("label_id", result.getData());

        return XmResultJson.success(data);
    }

    private LabelVO convert(LabelDTO labelDTO) {
        LabelVO res = new LabelVO();
        if (labelDTO == null) {
            return res;
        }
        res.setLabelGroupId(labelDTO.getTagGroupId());
        res.setId(labelDTO.getId());
        res.setName(labelDTO.getName());
        res.setAuto(labelDTO.getAuto());
        res.setManual(labelDTO.getManual());
        res.setOrgId(labelDTO.getOrgId());
        res.setBaseTime(new BaseTimeVo(labelDTO.getCreateTime(), labelDTO.getUpdateTime()));

        if (!CollectionUtils.isEmpty(labelDTO.getValues())) {
            List<LabelValueVO> valueVOS = labelDTO.getValues().stream().map(this::convert).collect(Collectors.toList());
            res.setValues(valueVOS);
        } else {
            res.setValues(new ArrayList<>(0));
        }

        return res;
    }

    private LabelValueVO convert(LabelValueDTO labelValueDTO) {
        LabelValueVO res = new LabelValueVO();
        if (labelValueDTO == null) {
            return res;
        }
        res.setId(labelValueDTO.getId());
        res.setValue(labelValueDTO.getValue());
        res.setSerial(labelValueDTO.getSerial());
        res.setOrgId(labelValueDTO.getOrgId());
        res.setAuto(labelValueDTO.getAuto());
        res.setManual(labelValueDTO.getManual());
        if(StringUtils.hasText(labelValueDTO.getCondition())){
            res.setCondition(JSONUtil.parseObj(labelValueDTO.getCondition()));
        }
        res.setBaseTime(new BaseTimeVo(labelValueDTO.getCreateTime(), labelValueDTO.getUpdateTime()));
        return res;
    }

    private CreateLabelParam convert(CreateLabelRequest request) {
        CreateLabelParam res = new CreateLabelParam();
        if (request == null) {
            return res;
        }
        res.setLabelGroupId(request.getLabelGroupId());
        res.setAuto(request.getAuto());
        res.setManual(request.getManual());
        res.setName(request.getName());
        if (!CollectionUtils.isEmpty(request.getInsertValues())) {
            List<CreateLabelValueParam> insertValueParams = request.getInsertValues().stream().map(this::convert).collect(Collectors.toList());
            res.setValues(insertValueParams);
        }
        return res;
    }

    private UpdateLabelParam convert(UpdateLabelRequest request) {
        UpdateLabelParam res = new UpdateLabelParam();
        if (request == null) {
            return res;
        }
        res.setId(request.getId());
        res.setLabelGroupId(request.getLabelGroupId());
        res.setAuto(request.getAuto());
        res.setManual(request.getManual());
        res.setName(request.getName());
        res.setDeleteValues(request.getDeleteValueIds());
        if (!CollectionUtils.isEmpty(request.getInsertValues())) {
            List<CreateLabelValueParam> insertValueParams = request.getInsertValues().stream().map(this::convert).collect(Collectors.toList());
            res.setInsertValues(insertValueParams);
        }
        if (!CollectionUtils.isEmpty(request.getUpdateValues())) {
            List<UpdateLabelValueParam> insertValueParams = request.getUpdateValues().stream().map(this::convert).collect(Collectors.toList());
            res.setUpdateValues(insertValueParams);
        }
        return res;
    }

    private UpdateLabelValueParam convert(UpdateLabelValueRequest request) {
        UpdateLabelValueParam res = new UpdateLabelValueParam();
        res.setId(request.getId());
        res.setSerial(request.getSerial());
        res.setValue(request.getValue());
        if (request.getCondition() != null) {
            res.setCondition(JSONUtil.toJsonStr(request.getCondition()));
        }
        return res;
    }

    private CreateLabelValueParam convert(CreateLabelValueRequest request) {
        CreateLabelValueParam res = new CreateLabelValueParam();
        res.setSerial(request.getSerial());
        res.setValue(request.getValue());
        if (request.getCondition() != null) {
            res.setCondition(JSONUtil.toJsonStr(request.getCondition()));
        }
        return res;
    }
}
